package com.my.exception;

import com.alibaba.fastjson.JSON;
import com.my.core.api.R;
import com.my.core.api.ResultCode;
import com.my.core.domain.exception.SecureException;
import com.my.core.domain.exception.ServiceException;
import com.my.core.util.WebUtil;
import com.my.event.publisher.ErrorLogPublisher;
import com.my.h2.logs.LogError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.Servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * @author timo 2021/2/25
 */
@Order
@Configuration
@ConditionalOnWebApplication(
        type = ConditionalOnWebApplication.Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class})
@RestControllerAdvice
public class CustomRestExceptionTranslator {
    private static final Logger log = LoggerFactory.getLogger(CustomRestExceptionTranslator.class);

    public CustomRestExceptionTranslator() {
    }

    @ExceptionHandler({ServiceException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R handleError(ServiceException e) {
        log.error("业务异常", e);
        return R.fail(e.getResultCode(), e.getMessage());
    }

    @ExceptionHandler({SecureException.class})
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public R handleError(SecureException e) {
        log.error("认证异常", e);
        return R.fail(e.getResultCode(), e.getMessage());
    }

    @ExceptionHandler({Throwable.class})
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R handleError(Throwable e) {
        log.error("服务器异常", e);
//        ErrorLogPublisher.publishEvent(e, UrlUtil.getPath(WebUtil.getRequest().getRequestURI()));
        LogError logError = new LogError();
        logError.setStatus(500);
        logError.setStackTrace(e.getLocalizedMessage());

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        // 获取请求信息
        String requestUrl = request.getRequestURL().toString();
        String method = request.getMethod();
        String remoteAddr = request.getRemoteAddr();

        // 获取请求参数
        StringBuilder params = new StringBuilder();
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String paramName = parameterNames.nextElement();
            params.append(paramName).append("=")
                    .append(request.getParameter(paramName)).append("&");
        }
        long beginTime = System.currentTimeMillis();
        long time = System.currentTimeMillis() - beginTime;

        // 获取请求头
        Map<String, String> requestHeaders = new HashMap<>();
        Enumeration<String> reqHeaderNames = request.getHeaderNames();
        while (reqHeaderNames.hasMoreElements()) {
            String headerName = reqHeaderNames.nextElement();
            requestHeaders.put(headerName, request.getHeader(headerName));
        }
        // 获取响应头
        Map<String, String> responseHeaders = new HashMap<>();
        if (response != null) {
            Collection<String> respHeaderNames = response.getHeaderNames();
            for (String headerName : respHeaderNames) {
                responseHeaders.put(headerName, response.getHeader(headerName));
            }
        }

        logError.setParams(params.length() > 0 ? params.substring(0, params.length() - 1) : "");
        logError.setRequestHeaders(JSON.toJSONString(requestHeaders));
        logError.setResponseHeaders(JSON.toJSONString(responseHeaders));
        logError.setRequestUrl(requestUrl);
        logError.setCreateTime(new Date());

        ErrorLogPublisher.publishEvent(e, WebUtil.getRequest().getRequestURI(),logError);
        return R.fail(ResultCode.INTERNAL_SERVER_ERROR,
                e.getMessage() == null ? ResultCode.INTERNAL_SERVER_ERROR.getMessage() : e.getMessage());
    }
}
